package registnet.base;

import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

import resources.Constants;

/**
 * This class provides default implementations for the <code>ITranscript</code> interface.
 */
public abstract class AbstractTranscript implements ITranscript {

	/**
	 * The student number of the student associated with the transcript.
	 */
	protected String studentNumber;
	
	/**
	 * The curriculum of the student associated with the transcript.
	 */
	protected ICurriculum curriculum;
	
	/**
	 * The list of courses taken associated with the transcript.
	 */
	protected List<ICourse> courses;
	
	/**
	 * Returns a sorted list of courses based on the year and semester in which the courses 
	 * are taken by the student.
	 * @param courses - the original list of courses to be sorted
	 * @return a sorted list of courses based on the year and semester in which the courses 
	 * are taken by the student
	 */
	private List<CourseTaken> sortByTimeTaken(List<CourseTaken> courses){
		List<CourseTaken> retval = courses;
		int n = courses.size();
		for(int i=0; i<n-1; i++){
			for(int j=0; j<(n-1-i); j++){
				CourseTaken a = courses.get(j);
				CourseTaken b = courses.get(j+1);
				if(CourseTaken.compareByTimeTaken(a,b)>0){
					courses.set(j,b);
					courses.set(j+1,a);
				}
			}
		}
		return retval;
	}
	
	@Override
	public void addCourse(ICourse course) {
		courses.add(course);
	}
	
	@Override
	public boolean contains(ICourse course) {
		ListIterator<ICourse> li = courses.listIterator();
		while(li.hasNext())
			if(course.equals(li.next()))
				return true;
		return false;
	}
	
	@Override
	public boolean contains(String courseCode) {
		ListIterator<ICourse> li = courses.listIterator();
		while(li.hasNext())
			if(courseCode.equals(li.next().getCourseCode()))
				return true;
		return false;
	}
	
	@Override
	public List<ICourse> getAllCoursesTaken() {
		return courses;
	}
	
	@Override
	public List<ICourse> getCoursesTaken(int year, int semester) {
		List<ICourse> retval = new Vector<ICourse>();
		ListIterator<ICourse> li = courses.listIterator();
		while(li.hasNext()){
			CourseTaken tmpCourse = (CourseTaken)li.next();
			if(year==tmpCourse.getYearTaken() && semester==tmpCourse.getSemesterTaken())
				retval.add(tmpCourse);
		}
		return retval;
	}
	
	@Override
	public List<ICourse> getCoursesTaken(int year) {
		List<ICourse> retval = new Vector<ICourse>();
		ListIterator<ICourse> li = courses.listIterator();
		while(li.hasNext()){
			CourseTaken tmpCourse = (CourseTaken)li.next();
			if(year==tmpCourse.getYearTaken())
				retval.add(tmpCourse);
		}
		return retval;
	}
	
	@Override
	public ICourse getRecentCourseTaken(String courseCode) {
		List<CourseTaken> listCourses = new Vector<CourseTaken>();
		ListIterator<ICourse> li = courses.listIterator();
		while(li.hasNext()){
			ICourse tmpCourse = li.next();
			if(courseCode.equals(tmpCourse.getCourseCode()))
				listCourses.add((CourseTaken)tmpCourse);
		}
		listCourses = sortByTimeTaken(listCourses);
		try{
			return listCourses.get(listCourses.size()-1);
		}catch(Exception e){
			return null;
		}
	}

	@Override
	public ICurriculum getCurriculum() {
		return curriculum;
	}
	
	@Override
	public double getGWA() {
		// TODO TODO Auto-generated method stub
		return 0;
	}
	
	@Override
	public String getStudentNumber() {
		return studentNumber;
	}
	
	@Override
	public int getUnitsCredited() {
		int retval = 0;
		Iterator<ICourse> ite = courses.iterator();
		while(ite.hasNext()){
			ICourse course = ite.next();
			if(course.getCourseCode().contains("PE ") || course.getCourseCode().contains("LTS ") || course.getCourseCode().contains("CWTS ") || course.getCourseCode().contains("ROTC ")){
				continue;
			}
			if(!(course instanceof CourseTaken) || !isCompleted(course.getCourseCode())){
				continue;
			}
			retval = retval + ((CourseTaken)course).getCredit();
		}
		return retval;
	}
	
	@Override
	public boolean isCompleted(String courseCode) {
		try{
			CourseTaken courseTaken = (CourseTaken)getRecentCourseTaken(courseCode);
			if (courseTaken.getReExam() != 0){
				if (courseTaken.getReExam() != Constants.MAP_GRADE_KEY.get("5") && courseTaken.getReExam() != Constants.MAP_GRADE_KEY.get("U"))
					return true;
			}else if (courseTaken.getGrade() != 0){
				if (courseTaken.getGrade() != Constants.MAP_GRADE_KEY.get("5") && courseTaken.getGrade() != Constants.MAP_GRADE_KEY.get("DRP.") && courseTaken.getGrade() != Constants.MAP_GRADE_KEY.get("U"))
					return true;
			}
		}catch(NullPointerException e){
			return false;
		}
		return false;
	}
	
	@Override
	public void setCurriculum(ICurriculum curriculum) {
		this.curriculum = curriculum;
	}
	
	@Override
	public void setStudentNumber(String studentNumber) {
		this.studentNumber = studentNumber;
	}

	@Override
	public int getUnitsCredited(int year, int semester){
		ListIterator<ICourse> iter = this.courses.listIterator();
		int totalUnits = 0;
		while(iter.hasNext()){
			CourseTaken course = (CourseTaken)iter.next();
			if(course.getCourseCode().contains("PE ") || course.getCourseCode().contains("LTS ") || course.getCourseCode().contains("CWTS ") || course.getCourseCode().contains("ROTC "))
				continue;
			if(course.getYearTaken() == year && course.getSemesterTaken() == semester){
				totalUnits += course.getUnit();
			}
		}
		return totalUnits;
	}
	
}
